/**
 * Copyright (C) 2009-2012, KingHool.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses.
 */
package com.kinghool.smodel.query;

import java.util.Map;

import com.kinghool.ebos.commons.Platform;
import com.kinghool.ebos.commons.utils.Assert;
import com.kinghool.ebos.commons.utils.Utils;
import com.kinghool.smodel.IModel;

/**
 * 
 * @Author Allen Deng(dengtailin@gmail.com) 
 */
public abstract class PropertyExpression {
	public static IExpression valueOf(final String queryExp) {
		if (Assert.isNotNullNotEmpty(queryExp)) {
			Map<String, String> expAttrs = Utils.newMap();
			boolean valid = true;
			for (String splitExp : queryExp.split(",")) {
				if (Assert.isNotNullNotEmpty(splitExp) 
					&& splitExp.indexOf("=") != -1
					&& !splitExp.startsWith("=")
					&& !splitExp.endsWith("=")) {
					String[] expPairs = splitExp.split("=");
					if (expPairs.length == 2) {
						if (Assert.isNotNullNotEmpty(expPairs[0]) && Assert.isNotNullNotEmpty(expPairs[1])) {
							expAttrs.put(expPairs[0].trim(), expPairs[1].trim());
						} else {
							valid = false;
						}
					} else {
						valid = false;
					}
				} else {
					valid = false;
				}
			}
			if (valid) {
				return equalAll(expAttrs);
			} else {
				Platform.getLogManager().warn("Invalid query expression:" + queryExp, Platform.getInstance());
				return IExpression.INVALID_EXPRESSION;
			}
		} else {
			return IExpression.VALID_EXPRESSION;
		}
	}
	
	public static IExpression equal(final String property, final String value){
		return new IExpression(){
			public boolean isMatched(IModel model) {
				Map<String, String> anotherValuePairs = getPropertyValuePairs(model);
				if (anotherValuePairs == null) return false;
				String compareValue = anotherValuePairs.get(property);
				return compareValue != null && compareValue.equals(value);
			}};		
	}

	public static IExpression equalAll(final Map<String, String> propValuePairs){
		return new IExpression(){
			public boolean isMatched(IModel model) {
				Map<String, String> anotherValuePairs = getPropertyValuePairs(model);
				if (anotherValuePairs == null) return false;
				for (String attribute : propValuePairs.keySet()) {
					 String compareValue = anotherValuePairs.get(attribute);
					 String value = propValuePairs.get(attribute);
					 if (compareValue == null || !compareValue.equals(value)) {
						 return false;
					 }
			     }
				 return true;
			}};		
	}
	
	public static IExpression and(final IExpression expr, final IExpression exprAnother){
		return new IExpression(){
			public boolean isMatched(IModel model) {
				return expr.isMatched(model) && exprAnother.isMatched(model);
			}
		};		
	}
	
	public static IExpression or(final IExpression expr, final IExpression exprAnother){
		return new IExpression(){
			public boolean isMatched(IModel model) {
				return expr.isMatched(model) || exprAnother.isMatched(model);
			}
		};		
	} 
	
	private static Map<String, String> getPropertyValuePairs(IModel model) {
		Map<String, String> props = Utils.newMap();
		for (String attr : model.getAllProperties()) {
			props.put(attr, model.getStringProperty(attr));
		}
		return props;
	} 
}